package com.sonic.jms.base;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;

import javax.ejb.EJBException;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import ch.softwired.mobileibus.qos.ProtocolStackRegistry;
import ch.softwired.mobileibus.qos.QoSConst;

import com.sonic.jms.exceptions.MQuotesMapperException;
import com.sonic.jms.utils.xmlmapper.MQCastorXmlMapper;
import com.sonic.log.ejb.impl.MQLogger;

/** 
 * Monitor base meesage consumer class.<br>
 * There is P2P communication with ESB and MonitorMessageProcessor.
 * 
 * @author <b>Adam Dec/b> for <b><I>iBroker</i></b><br> Copyright &#169; 2008/2009
 * @since 25-09-2008
 * @category BROKER BASE JMS BEAN
 * @version 1.0
 */
public class MQuotesMsgProcessorBase {
	public static MQLogger logger       = new MQLogger(MQuotesMsgProcessorBase.class, "MQ-PROCESSOR-BASE");
    
	private SimpleDateFormat dateFormatter = new SimpleDateFormat("ss:SS");
	
	public MQuotesMsgProcessorBase() {}
	
	private static final String IBUS_HOST_NAME = "localhost";
	
	private static final String SOCKET_CONNECTION_URL 	= "socket://"+IBUS_HOST_NAME+":8738";
	
	@SuppressWarnings("unused")
    private static final String HTTP_CONNECTION_URL 	= "http://"+IBUS_HOST_NAME+":8080/servlet/ch.softwired.gateway.servlets.MidpServlet";
	
	@SuppressWarnings("unused")
    private static final String UDP_CONNECTION_URL 		= "datagram://"+IBUS_HOST_NAME+":8738";
	
	protected static String CONNECTION_URL 				= SOCKET_CONNECTION_URL;	
	
	protected static final String SESSION_ID 	= "queueProcessorSessionId.";
	private static final String QOS_NAME      	= "qos-tcp-topic-prod";
	
	static InitialContext context = null;
	static {
		try {
	        registerProtocolStack();
	        context = createInitialContext();
        } catch (JMSException e) {
        	logger.debug("static", " --- [ERROR] MQuotesMsgProcessorBase, could not register iBus protocol stack!");
        	logger.error("static", Integer.parseInt(e.getErrorCode()), e.getMessage());
        	throw new EJBException(e);
        } catch(NamingException e) {
        	logger.debug("static", " --- [ERROR] MQuotesMsgProcessorBase, could not create initial context for iBus!");
        	logger.debug("static", e.getMessage());
        	throw new EJBException(e);
        }
	}	
	
	public static InitialContext getContext() {
    	return context;
    }

	private static void registerProtocolStack() throws JMSException {
		final String methodName = "registerProtocolStack";
		Hashtable<String, String> qosParams = new Hashtable<String, String>();		
		QoSConst.checkAndSetProperty(qosParams, QoSConst.KEY_RESET_STORE, "true");
		QoSConst.checkAndSetProperty(qosParams, QoSConst.KEY_NODELAY, "true");
		QoSConst.checkAndSetProperty(qosParams, QoSConst.KEY_SEND_DELAY, "0");
		
		ProtocolStackRegistry.deregisterQosNamed(QOS_NAME);		
		logger.debug(methodName, " --- [INFO] Protocol stack has tried to unregister " + QOS_NAME);
		
		if(ProtocolStackRegistry.isValidSessionId(SESSION_ID))
			logger.debug(methodName, " --- [INFO] Protocol stack has already detected session id: " + SESSION_ID);
	
		ProtocolStackRegistry.registerQos(QOS_NAME,
										  CONNECTION_URL,
										  qosParams,
										  SESSION_ID + System.currentTimeMillis(), 
										  false,										  				
										  false, 		
										  false); 		
		logger.debug(methodName, " --- [INFO] Protocol stack has been successfully registered.");
		logger.debug(methodName, " --- [INFO] Connecting to gateway using: " + CONNECTION_URL);
	}
	
	private static InitialContext createInitialContext() throws NamingException {
		final String methodName = "createInitialContext";
		Hashtable<String, String> jndiEnv = new Hashtable<String, String>();
		jndiEnv.put(ch.softwired.mobileibus.jndi.Context.INITIAL_CONTEXT_FACTORY, "ch.softwired.mobileibus.jndi.InitialContextFactory");
		jndiEnv.put(ch.softwired.mobileibus.jndi.Context.QOS_NAME, QOS_NAME);
		InitialContext ctx = new InitialContext(jndiEnv);		
		logger.debug(methodName, " --- [INFO] InitialContext has been successfully created.");
		return ctx;
	}
	
	/**
	 * Creates queue connection for destination queue.
	 * 
	 * @param QueueConnectionFactory queueConnectionFactory
	 * @return QueueConnection
	 * @throws JMSException
	 */
    protected QueueConnection createQueueConnection(final QueueConnectionFactory  queueConnectionFactory) throws JMSException {
    	final String methodName = "createQueueConnection()";
    	final QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();
    	logger.debug(methodName, " --- QueueConnection has been succesfully created.");
		return queueConnection;
    }  
    
	/**
	 * Creates topic connection for destination topic.
	 * 
	 * @param TopicConnectionFactory  topicConnectionFactory
	 * @return TopicConnection
	 * @throws JMSException
	 */
    protected TopicConnection createTopicConnection(final TopicConnectionFactory  topicConnectionFactory) throws JMSException {
    	final String methodName = "createTopicConnection()";
    	final TopicConnection topicConnection = topicConnectionFactory.createTopicConnection();
    	logger.debug(methodName, " --- TopicConnection has been succesfully created.");
		return topicConnection;
    }
    
    /**
     * Creates queue session for destination queue.
     * 
     * @param QueueConnection queueConnection
     * @return QueueSession
     * @throws JMSException
     */
    protected QueueSession createQueueSession(final QueueConnection queueConnection) throws JMSException {
    	final String methodName = "createQueueSession()";
    	final QueueSession queueSession = queueConnection.createQueueSession(false, Session.DUPS_OK_ACKNOWLEDGE);
    	logger.debug(methodName, " --- QueueSession has been succesfully created.");    	
 		return queueSession;
    } 
    
    /**
     * Creates topic session for destination topic.
     * 
     * @param TopicConnection topicConnection
     * @return TopicSession
     * @throws JMSException
     */
    protected TopicSession createTopicSession(final TopicConnection topicConnection) throws JMSException {
    	final String methodName = "createTopicSession()";
    	final TopicSession topicSession = topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    	logger.debug(methodName, " --- TopicSession has been succesfully created.");    	
 		return topicSession;
    }
    
    /**
     * Creates queue sender for destination queue.
     * 
     * @param QueueSession queueSession
     * @param Queue queue
     * @return QueueSender
     * @throws JMSException
     */
    protected QueueSender createQueueSender(final QueueSession queueSession, final Queue queue) throws JMSException {
    	final String methodName = "createQueueSender()";
    	final QueueSender queueSender = queueSession.createSender(queue);    	
    	logger.debug(methodName, " --- QueueSender has been succesfully created for destination queue: " + queue.getQueueName());    	
		return queueSender;
    } 
    
    /**
     * Creates topic publisher for destination topic.
     * 
     * @param TopicSession topicSession
     * @param Topic topic
     * @return TopicPublisher
     * @throws JMSException
     */
    protected TopicPublisher createTopicPublisher(final TopicSession topicSession, final Topic topic) throws JMSException {
    	final String methodName = "createQueueSender()";
    	final TopicPublisher topicPublisher = topicSession.createPublisher(topic);    	
    	logger.debug(methodName, " --- TopicPublisher has been succesfully created for destination topic: " + topic.getTopicName());    	
		return topicPublisher;
    }
    
    /**
     * Creates object from input stream (XML).
     * 
     * @param byte[] buffer
     * @return Object
     * @throws Exception
     */
    protected Object readObjectAsXmlFrom(final byte[] buffer) throws MQuotesMapperException {
    	return MQCastorXmlMapper.mapXmlToObject(new InputStreamReader(new ByteArrayInputStream(buffer)));
    }
    
    /**
     * Calculates send message timestamp.
     * 
     * @param sendTime
     * @return diff
     *
     * @version 1.0
     * @since 2008-12-29
     * @author Adam Dec
     */
    protected String calculateTimestamp(final long sendTime) {
    	long currTime   = System.currentTimeMillis();
    	final Date date = new Date(currTime-sendTime);
    	return "Send timestamp: " + dateFormatter.format(date);    	
    }
}